package com.eshop.modules.product.service.impl;

import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.eshop.api.BusinessException;
import com.eshop.api.EshopException;
import com.eshop.common.service.impl.BaseServiceImpl;
import com.eshop.dozer.service.IGenerator;
import com.eshop.enums.ProductTypeEnum;
import com.eshop.exception.BadRequestException;
import com.eshop.modules.product.domain.StoreProductAttr;
import com.eshop.modules.product.domain.StoreProductAttrValue;
import com.eshop.modules.product.service.StoreProductAttrResultService;
import com.eshop.modules.product.service.StoreProductAttrService;
import com.eshop.modules.product.service.StoreProductAttrValueService;
import com.eshop.modules.product.service.dto.AttrValueDto;
import com.eshop.modules.product.service.dto.FromatDetailDto;
import com.eshop.modules.product.service.dto.ProductFormatDto;
import com.eshop.modules.product.service.mapper.StoreProductAttrMapper;
import com.eshop.modules.product.service.mapper.StoreProductAttrValueMapper;
import com.eshop.modules.product.vo.StoreProductAttrQueryVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

@Service
@Transactional(propagation = Propagation.REQUIRED, rollbackFor = { Exception.class })
public class StoreProductAttrServiceImpl extends BaseServiceImpl<StoreProductAttrMapper, StoreProductAttr> implements StoreProductAttrService
{
    @Autowired
    private IGenerator generator;
    @Autowired
    private StoreProductAttrMapper yxStoreProductAttrMapper;
    @Autowired
    private StoreProductAttrValueMapper yxStoreProductAttrValueMapper;
    @Autowired
    private StoreProductAttrValueService storeProductAttrValueService;
    @Autowired
    private StoreProductAttrResultService storeProductAttrResultService;
    
    @Transactional(rollbackFor = { Exception.class })
    public void insertYxStoreProductAttr(final List<FromatDetailDto> items, final List<ProductFormatDto> attrs, final Long productId) {
        final List<StoreProductAttr> attrGroup = new ArrayList<StoreProductAttr>();
        for (final FromatDetailDto fromatDetailDto : items) {
            final StoreProductAttr storeProductAttr = StoreProductAttr.builder().productId(productId).attrName(fromatDetailDto.getValue()).attrValues(StrUtil.join((CharSequence)",", new Object[] { fromatDetailDto.getDetail() })).build();
            attrGroup.add(storeProductAttr);
        }
        final List<StoreProductAttrValue> valueGroup = new ArrayList<StoreProductAttrValue>();
        for (final ProductFormatDto productFormatDto : attrs) {
            if (productFormatDto.getPinkStock() > productFormatDto.getStock() || productFormatDto.getSeckillStock() > productFormatDto.getStock()) {
                throw new BadRequestException("活动商品库存不能大于原有商品库存");
            }
            final List<String> stringList = new ArrayList<String>(productFormatDto.getDetail().values());
            Collections.sort(stringList);
            final StoreProductAttrValue storeProductAttrValue = StoreProductAttrValue.builder().productId(productId).sku(StrUtil.join((CharSequence)",", new Object[] { stringList })).price(BigDecimal.valueOf(productFormatDto.getPrice())).cost(BigDecimal.valueOf(productFormatDto.getCost())).otPrice(BigDecimal.valueOf(productFormatDto.getOtPrice())).unique(IdUtil.simpleUUID()).image(productFormatDto.getPic()).barCode(productFormatDto.getBarCode()).weight(BigDecimal.valueOf(productFormatDto.getWeight())).volume(BigDecimal.valueOf(productFormatDto.getVolume())).brokerage(BigDecimal.valueOf(productFormatDto.getBrokerage())).brokerageTwo(BigDecimal.valueOf(productFormatDto.getBrokerageTwo())).stock(productFormatDto.getStock()).integral(productFormatDto.getIntegral()).pinkPrice(BigDecimal.valueOf((productFormatDto.getPinkPrice() == null) ? 0.0 : productFormatDto.getPinkPrice())).seckillPrice(BigDecimal.valueOf((productFormatDto.getSeckillPrice() == null) ? 0.0 : productFormatDto.getSeckillPrice())).pinkStock((productFormatDto.getPinkStock() == null) ? 0 : productFormatDto.getPinkStock()).seckillStock((productFormatDto.getSeckillStock() == null) ? 0 : productFormatDto.getSeckillStock()).build();
            valueGroup.add(storeProductAttrValue);
        }
        if (attrGroup.isEmpty() || valueGroup.isEmpty()) {
            throw new BusinessException("请设置至少一个属性!");
        }
        this.clearProductAttr(productId);
        this.saveBatch((Collection)attrGroup);
        this.storeProductAttrValueService.saveBatch((Collection)valueGroup);
        final Map<String, Object> map = new LinkedHashMap<String, Object>();
        map.put("attr", items);
        map.put("value", attrs);
        this.storeProductAttrResultService.insertYxStoreProductAttrResult(map, productId);
    }
    
    private void clearProductAttr(final Long productId) {
        if (ObjectUtil.isNull(productId)) {
            throw new EshopException("产品不存在");
        }
        this.yxStoreProductAttrMapper.delete(Wrappers.<StoreProductAttr>lambdaQuery().eq(StoreProductAttr::getProductId, productId));
        this.yxStoreProductAttrValueMapper.delete(Wrappers.<StoreProductAttrValue>lambdaQuery().eq(StoreProductAttrValue::getProductId, productId));
    }
    
    public void incProductAttrStock(final Integer num, final Long productId, final String unique, final String type) {
        if (ProductTypeEnum.COMBINATION.getValue().equals(type)) {
            this.yxStoreProductAttrValueMapper.incCombinationStockDecSales(num, productId, unique);
        }
        else if (ProductTypeEnum.SECKILL.getValue().equals(type)) {
            this.yxStoreProductAttrValueMapper.incSeckillStockDecSales(num, productId, unique);
        }
        else {
            this.yxStoreProductAttrValueMapper.incStockDecSales(num, productId, unique);
        }
    }
    
    public void decProductAttrStock(final int num, final Long productId, final String unique, final String type) {
        int res = 0;
        if (ProductTypeEnum.COMBINATION.getValue().equals(type)) {
            res = this.yxStoreProductAttrValueMapper.decCombinationStockIncSales(num, productId, unique);
        }
        else if (ProductTypeEnum.SECKILL.getValue().equals(type)) {
            res = this.yxStoreProductAttrValueMapper.decSeckillStockIncSales(num, productId, unique);
        }
        else {
            res = this.yxStoreProductAttrValueMapper.decStockIncSales(num, productId, unique);
        }
        if (res == 0) {
            throw new EshopException("商品库存不足");
        }
    }
    
    public StoreProductAttrValue uniqueByAttrInfo(final String unique) {
        return (StoreProductAttrValue)this.yxStoreProductAttrValueMapper.selectOne(Wrappers.<StoreProductAttrValue>lambdaQuery().eq(StoreProductAttrValue::getUnique, unique));
    }

    /**
     * select * from store_product_attr_value where product_id=30
     * select * from store_product_attr_result where product_id=30
     * select * from store_product_attr where product_id=30
     *
     */
    public Map<String, Object> getProductAttrDetail(final long productId) {
        // 使用 yxStoreProductAttrMapper 查询指定产品的所有属性记录，并按 attrValues 升序排序
        final List<StoreProductAttr> storeProductAttrs = this.yxStoreProductAttrMapper.selectList((Wrappers.<StoreProductAttr>lambdaQuery().eq(StoreProductAttr::getProductId, productId)).orderByAsc(StoreProductAttr::getAttrValues));
        // 使用 storeProductAttrValueService 查询指定产品的所有属性值记录，并将结果转换为一个 Map，
        // 键为 sku，值为对应的 StoreProductAttrValue 对象。
        final List<StoreProductAttrValue> productAttrValues = this.storeProductAttrValueService.list(Wrappers.<StoreProductAttrValue>lambdaQuery().eq(StoreProductAttrValue::getProductId, productId));
        final Map<String, StoreProductAttrValue> map = productAttrValues.stream()
                .collect(Collectors.toMap((StoreProductAttrValue::getSku), p -> p));

        // 遍历第一步获取的产品属性列表（storeProductAttrs）单纯就是把字符串逗号分割的，拆解出来变成对象而已：
        final List<StoreProductAttrQueryVo> storeProductAttrQueryVoList = new ArrayList<StoreProductAttrQueryVo>();
        for (final StoreProductAttr attr : storeProductAttrs) {
            // 一、将每个属性的 attrValues 字符串拆分成一个字符串列表（stringList）。
            final List<String> stringList = Arrays.asList(attr.getAttrValues().split(","));
            // 二、对于 stringList 中的每个字符串，创建一个新的 AttrValueDto 对象，并将该字符串放入 attr 属性，然后将这些对象添加到 attrValueDTOS 列表中。
            final List<AttrValueDto> attrValueDTOS = new ArrayList<AttrValueDto>();
            for (final String str : stringList) {
                final AttrValueDto attrValueDTO = new AttrValueDto();
                attrValueDTO.setAttr(str);
                attrValueDTOS.add(attrValueDTO);
            }
            // 三、使用对象转换工具（如ModelMapper或Apache BeanUtils）将当前属性（attr）转换为 StoreProductAttrQueryVo 类型的对象，
            // 并设置其 attrValue 属性为之前构建的 attrValueDTOS 列表，以及 attrValueArr 属性为原始的 stringList。
            final StoreProductAttrQueryVo attrQueryVo = (StoreProductAttrQueryVo)this.generator.convert(attr, (Class)StoreProductAttrQueryVo.class);
            attrQueryVo.setAttrValue(attrValueDTOS);
            attrQueryVo.setAttrValueArr(stringList);
            // 四、将转换后的 StoreProductAttrQueryVo 对象添加到 storeProductAttrQueryVoList 列表中。
            storeProductAttrQueryVoList.add(attrQueryVo);
        }
        final Map<String, Object> returnMap = new LinkedHashMap<String, Object>(2);
        returnMap.put("productAttr", storeProductAttrQueryVoList);
        returnMap.put("productValue", map);
        return returnMap;
    }
}
